#ifndef _GOVT_CHARACTER_H
#define	_GOVT_CHARACTER_H
/*******************************************************************************
 ** Name: character.cpp                                                       **
 ** Description: WorldObject-derived container objects                        **
 **                                                                           **
 ** Open Source Initiative (OSI) Approved License                             **
 **                                                                           **
 ** The contents of this file are subject to the terms of the                 **
 ** Common Development and Distribution License, Version 1.0 only             **
 ** (the "License").  You may not use this file except in compliance          **
 ** with the License.                                                         **
 **                                                                           **
 ** You can find a copy of the license in the LICENSE file within             **
 ** this distribution or at $WIKI/display/GOVT/License-software.              **
 ** Software distributed under the License is distributed on an "AS IS"       **
 ** basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.           **
 ** See the License for the specific language governing permissions           **
 ** and limitations under the License.                                        **
 **                                                                           **
 ** When distributing Covered Code, include this CDDL header in each          **
 ** file and include the License file at $GAME_DIR/LICENSE.                   **
 ** If applicable, add the following below this header, with the indicated    **
 ** fields enclosed by brackets "[]" replaced with your own identifying       **
 ** information: Portions Copyright [yyyy] [name of copyright owner]          **
 **                                                                           **
 **                                                                           **
 ** Copyright (c) 2009-2012  Barry Gian James <gian@gamingods.net>            **
 ** All rights reserved.                                                      **
 ******************************************************************************/
// Modified $Date$ by $Author$
#define _character_h_ID    "$Id$"
#include <math.h>
#include <vector>
#include <odb/core.hxx>
#include <string>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include "object.hpp"
#include "condition.hpp"
#include "faction.hpp"
//#include "agency.hpp"
#include "professions.hpp"
#include "background.hpp"
#include "occupation.hpp"
#include "quest.hpp"
#include "training.hpp"
#include "container.hpp"
#include "visitor.hpp"
#include "common.hpp"
#include "cmd.hpp"
#include "policy.hpp"
#include "network.hpp"

#define MAX_CHAR_LVL        200		//!< Wow, 200? Really?
#define MAX_USERNAME_LEN	128
#define MAX_PASSWD_LEN		12
#define DEFAULT_STAT		8

// Character flags
#define	CHAR_AUTOJOIN_CHAN	0x0001
#define CHAR_OOC		0x0002	// is player in character or ooc?
#define CHAR_SUSPECT		0x0004	// report some activity to controls
#define CHAR_CAN_BUILD		0x0008	// a builder
#define CHAR_PVP		0x0010	// char is set pvp
#define CHAR_ALLOW_TELL		0x0020	// player allows whispers
#define CHAR_ALLOW_COLOR_THEMES 0x0040	// allow setting up color themes
#define CHAR_HANDLER		0x0080
#define CHAR_CONTROL		0x0100	// Control
#define CHAR_DIRECTOR		0x0200	// players who manage gameplay and content
#define CHAR_GOD		0x0400	// one and only
#define CHAR_MISSION_CTRL	0x0800	// Mission Control
#define CHAR_AGENCY_CTRL	0x1000	// Agency Control
#define CHAR_GAME_CTRL		0x2000	// Game Control
#define CHAR_FX_SENSITIVE	0x4000

enum class GenderType { Male, Female, Androgenous, Transgendered };
extern const char * GenderStr[];

// The following structure will be boilerplated in each character indicating
// what item is equipped in what slot
#pragma db value
struct WearLocations
{
#pragma db default(0)
	entity_t	head;
#pragma db default(0)
	entity_t	larm;
#pragma db default(0)
	entity_t	rarm;
#pragma db default(0)
	entity_t	lleg;
#pragma db default(0)
	entity_t	rleg;
#pragma db default(0)
	entity_t	chest;
#pragma db default(0)
	entity_t	back;
#pragma db default(0)
	entity_t	feet;
#pragma db default(0)
	entity_t	neck;
#pragma db default(0)
	entity_t	waist;
#pragma db default(0)
	entity_t	lfinger;
#pragma db default(0)
	entity_t	rfinger;
#pragma db default(0)
	entity_t	legs;
#pragma db default(0)
	entity_t	lhand;
#pragma db default(0)
	entity_t	rhand;
#pragma db default(0)
	entity_t	lwrist;
#pragma db default(0)
	entity_t	rwrist;

	WearLocations();
};

// Command/Power Hierarchy
enum class power {
    civilian,   //!< rank 0. guest.
    agent,      //!< rank 1. field agent. most players.
    handler,    //!< rank 2. mission generator.
    control,    //!< rank 3. agency executive.
    director,	//!< rank 4. board of directors sets game policies
    admin       //!< OOC game admin
};

//! General schedule ranks
enum class gs
{
    gs1,        gs2,
    gs3,        gs4,
    gs5,        gs6,
    gs7,        gs8,
    gs9,        gs10,
    gs11,       gs12,
    gs13,       gs14,
    gs15,
    //! Senior Executive Service ranks
    ses1,       ses2,
    ses3,       ses4,

    max
};

// TODO - Maybe remove this.
// Deprecated
enum class Allegience {
	none, self, agency, higher, truth, knowledge, justice
};

class Level
{
public:
	static unsigned int	XPNeededForLevel(int l) { return (pow(l,3.01)); }
	static unsigned int	XPTillNextLevel(int l, unsigned int xp) { return (XPNeededForLevel(l) - xp); }
};

// This object is used to store a character's inventory
//#pragma db object table("character_inventory")
//struct InventoryData
//{
//	InventoryData() { _id = _owner = _item = 0; }
//
//	#pragma db id auto
//	entity_t	_id;
//	entity_t	_owner;
//	entity_t	_item;
//};

class Dossier;
class Agency;
//! @class Character
//! All players are characters.
#pragma db object polymorphic table("character_base")
class Character : public WorldObject, public subscriber
{
public:
    Character();
    Character(const std::string & n, const std::string & t, ObjectType tt);
    Character(const Character& orig);
    ~Character();

    SMART_PTR_DECL(Character);

    static pointer Create(const std::string & n, const std::string & t, ObjectType tt) {
    	return boost::make_shared<Character>(n,t,tt);
    }

    virtual std::string TypeToStr() { return "Character"; }

	// deferred
	virtual void	deliver(const std::string &msg) { }

    // Getters
    const int		Level() const { return _lvl; }
    const int  XP() const { return _xp; }
    const int  Wealth() const { return _scratch; }
    const bool  FXSensitive() const { return _flags & CHAR_FX_SENSITIVE; }
    const std::string&    Height() const  { return _height; }
    const std::string&    Eyes() const  { return _eyes; }
    const std::string&    Hair() const  { return _hair; }
    const unsigned int	  Age() const  { return _age; }
    const std::string&	  Codename() const  { return _codename; }
    const entity_t		Faction() const  { return _agency; }
    const GenderType	Gender() const  { return _gender; }
    const unsigned int	Strength()	{ return _str; }
    const unsigned int 	Dexterity() { return _dex; }
    const unsigned int 	Constitution() { return _con; }
    const unsigned int 	Intelligence() { return _inte; }
    const unsigned int	Aura() const { return _aur; }
    const unsigned int	Wit() const { return _wit; }
    const unsigned int 	Willpower() const { return _will; }
    const unsigned int	Genius() const { return _gen; }
    const unsigned int 	MaxStrength() { return _str_max; }
    const unsigned int 	MaxDexterity() { return _dex_max; }
    const unsigned int 	MaxConstitution() { return _con_max; }
    const unsigned int 	MaxIntelligence() { return _inte_max; }
    const unsigned int	MaxAura() const { return _aur_max; }
    const unsigned int	MaxWit() const { return _wit_max; }
    const unsigned int 	MaxWillpower() const { return _will_max; }
    const unsigned int	MaxGenius() const { return _gen_max; }

    const unsigned int	AttributeBonus(const unsigned int a) {
    	return (floor((a/2) - 5));
    }

    const unsigned int 	Defense() const { return _def; }
    const unsigned int 	Avoidance() const { return _avd; }
    const unsigned int 	Initiative() const { return _init; }
    const unsigned int 	MaxDefense() { return _def_max; }
    const unsigned int 	MaxAvoidance() { return _avd_max; }
    const unsigned int 	MaxInitiative() { return _init_max; }

    const unsigned int 	Fort() { return _fort; }
    const unsigned int 	Will() { return _will; }
    const unsigned int 	Reflex() { return _reflex; }
    const unsigned int 	Recovery() { return _recovery; }
    const unsigned int 	MaxFort() { return _fort_max; }
    const unsigned int 	MaxWill() { return _will_max; }
    const unsigned int 	MaxReflex() { return _reflex_max; }
    const unsigned int 	MaxRecovery() { return _recovery_max; }
    const std::string & TitlePrefix() const { return _title_prefix; }
    const std::string & TitleSuffix() const { return _title_suffix; }

    // Setters
    void	Level(const int l) { _lvl = l; }
    void	XP(const int x) { _xp = x; }
    void	AddXP(const int x) { _xp += x; }
    void	Wealth(const int w) { _scratch = w; }
    void	AddScratch(const int s) { _scratch += s; }
    void	Height(const std::string & h) { _height = h; }
    void	Eyes(const std::string & e) { _eyes = e; }
    void	Hair(const std::string & h) { _hair = h; }
    void	Age(const unsigned int a) { _age = a; }
    void	Codename(const std::string & c) { _codename = c; }
    void 	Faction(const entity_t f) { _agency = f; }
    void	Gender(const GenderType & g) { _gender = g; }
    void    Strength(const unsigned int v) { _str = v; }
    void      Dexterity(const unsigned int v) { _dex = v; }
    void      Constitution(const unsigned int v) { _con = v; }
    void      Intelligence(const unsigned int v) { _inte = v; }
    void	Aura(const unsigned int v) { _aur = v; }
    void	Wit(const unsigned int v) { _wit = v; }
    void	Willpower(const unsigned int v) { _wil = v; }
    void	Genius(const unsigned int v) { _gen = v; }
    void     MaxStrength(const unsigned int v) { _str_max = v; }
    void      MaxDexterity(const unsigned int v) { _dex_max = v; }
    void      MaxConstitution(const unsigned int v) { _con_max = v; }
    void      MaxIntelligence(const unsigned int v) { _inte_max = v; }
    void	MaxAura(const unsigned int v) { _aur_max = v; }
    void	MaxWit(const unsigned int v) { _wit_max = v; }
    void	MaxWillpower(const unsigned int v) { _wil_max = v; }
    void	MaxGenius(const unsigned int v) { _gen_max = v; }
    void      Defense(const unsigned int v) { _def = v; }
    void      Avoidance(const unsigned int v) { _avd = v; }
    void      Initiative(const unsigned int v) { _init = v; }
    void      MaxDefense(const unsigned int v) { _def_max = v; }
    void      MaxAvoidance(const unsigned int v) { _avd_max = v; }
    void      MaxInitiative(const unsigned int v) { _init_max = v; }
    void      Fort(const unsigned int v) { _fort = v; }
    void      Will(const unsigned int v) { _will = v; }
    void      Reflex(const unsigned int v) { _reflex = v; }
    void      Recovery(const unsigned int v) { _recovery = v; }
    void	TitlePrefix(const std::string & t) { _title_prefix = t; }
    void	TitleSuffix(const std::string & t) { _title_suffix = t; }



    int		IsControl() { return BMCHK(_flags,CHAR_CONTROL); }
    int		IsHandler() { return BMCHK(_flags,CHAR_HANDLER); }
    int		IsBuilder() { return BMCHK(_flags,CHAR_CAN_BUILD); }
    int		IsGod() { return BMCHK(_flags,CHAR_GOD); }
    int		IsDirector() { return BMCHK(_flags,CHAR_DIRECTOR); }
    int		IsFXSensitive() { return _flags & CHAR_FX_SENSITIVE; }

    void	IncrLevel() { ++_lvl; }
    double &	Consider() { return _consider; }

    int		Actionable();
    void	accept(Pattern::Visitor & v);
    //! Recalculates all stats based on worn, wielded, bkg,occ,prof,etc.
    //! This is an expensive operation. Use with caution.
    void	UpdateStats();


//	// Commands
//	void		AddCmd(boost::shared_ptr<Command> & c) { commands.push_back(c); }
//	void		DelCmd(std::string &);
//	boost::shared_ptr<Command> & GetCmd(std::string &);

    // TODO Figure out how to set wielding/wield items in left/right hand
    // and get the item wielded from either or both hands.
	bool		Wielding();
	WearLocations & WearLocation() { return _wearLocations; }
	// Conditions
	void		AddCondition(ConditionNode n) { _cond.push_back(n); }
	std::vector<ConditionNode> & Conditions() { return _cond; }

    // Inventory
    std::vector<entity_t> &	Inventory() { return _inventory; }
    entity_t		FindInventoryItem(const std::string&);
    void			RemoveInventoryItem(entity_t);
    void			AddInventoryItem(entity_t);	//!< don't forget to check encumbrance when adding to inventory

private:
    friend class odb::access;
    std::string		_codename;
    std::string    	_height;
    std::string   	_eyes;
    std::string    	_hair;
    unsigned int	_age;
    GenderType		_gender;

    // Change in support of ODB ORM types. ~gian
    unsigned int		_str,_dex,_con,_inte,_aur, _wit, _wil, _gen;
    unsigned int		_str_max,_dex_max,_con_max,_inte_max;
    unsigned int		_aur_max, _wit_max, _wil_max, _gen_max;

    unsigned int		_def,_avd,_init,_speed;
    unsigned int		_def_max, _avd_max, _init_max,_speed_max;

    unsigned int		_fort,_will,_reflex,_recovery;
    unsigned int		_fort_max,_will_max,_reflex_max,_recovery_max;

    ulong  _xp;	// int max = 4.2B
    ulong	_scratch;
    int     _lvl;    //!< career level (ie 3)
    double	_consider;	// this is what 'consider' compares.

    entity_t	_agency;

    // Condition
#pragma db unordered
    std::vector<ConditionNode>	_cond;

    std::string		_title_prefix;
    std::string		_title_suffix;

#pragma db unordered
    std::vector<entity_t>	_inventory;

	WearLocations	_wearLocations;

	// Policies are the logic modules that govern how events will be handled
	//std::vector<boost::shared_ptr<Policy> > _policies;

//	std::vector<boost::shared_ptr<Command> > commands;
};

// Character Titles Table
enum class TitleType { Prefix, Suffix };
#pragma db object table("character_titles")
struct CharacterTitlesTable
{
#pragma db id auto
	entity_t	id_;
	entity_t	idcharacter_;
	TitleType	type_;
	std::string	name_;
};

class Team;

// Design RC-0.1
#pragma db object table("characters")
class PC : public Character,
	public boost::enable_shared_from_this<PC>
{
public:
	SMART_PTR_DECL(PC);

	PC();
	PC(const std::string & n, const std::string & t);

	void	accept(Pattern::Visitor & v);

	void	deliver(const std::string &msg);


    // Getters
    const std::string& Profession() const { return _profession; }
    const std::string& Background() const { return _background; }
    const std::string& Occupation() const { return _occupation; }
    const unsigned int BackgroundLevel() const { return _bkglvl; }
    const entity_t		Rank() const { return _rank; }
    const int			PlayerKills() const { return _pkills; }
    const int			PlayerDeaths() const { return _pdeaths; }
    const unsigned int	Encumbrance() const { return _encumbranceCurr; }
    const unsigned int	EncumbranceMax() const { return _encumbranceMax; }
    const unsigned int	EncumbrancePct() const { return _encumbrancePct; }
    const int   Renown() const { return _renown; }
    const int	Liability() const { return _liability; }
    const int	Capital() const { return _capital; }
    const agency::deptnum Dept() const { return _dept; }
    const int	Wanted() const { return _wanted; }
    const bool	IsOnTeam() const { return _on_team; }

    // Setters
    void	Wanted(const int w) { _wanted = w; }
    void	Renown(const int & r) { _renown = r; }
    void	Liability(const int l) { _liability = l; }
    void	Capital(const int c) { _capital = c; }
    void	Profession(const std::string & p) { _profession = p; }
    void	Background(const std::string & b) { _background = b; }
    void	Occupation(const std::string & o) { _occupation = o; }
    void	BackgroundLevel(const unsigned int b) { _bkglvl = b; }
    void	Rank(const entity_t r) { _rank = r; }
    void	PlayerKills(const int pk) { _pkills = pk; }
    void	PlayerDeaths(const int pd) { _pdeaths = pd; }
    void	Encumbrance(const unsigned int e) {_encumbranceCurr = e; }
    void	EncumbranceMax(const unsigned int e) { _encumbranceMax = e; }
    void	EncumbrancePct(const unsigned int e ) { _encumbrancePct = e; }
    void	Dept(const agency::deptnum d) { _dept = d; }
    void	Renown(const int r) { _renown = r; }
    void	IsOnTeam(bool b) { _on_team = b; }

    // Quests
	bool		QuestCompleted(std::string &);
	void		AddQuest(entity_t);
	void		CompleteQuest(entity_t);

	// Team support
	void	JoinTeam(boost::shared_ptr<Team> t);
	void	StartTeam(const std::string & n);
	void	LeaveTeam();

private:
    friend class odb::access;

	std::string		_profession;
	std::string		_background;
	std::string		_occupation;
	unsigned int			_bkglvl;
	entity_t		_rank;		// faction rank
    int		_pkills;		//!< number of player kills
    int		_pdeaths;		//!< number of deaths
#pragma db column("encumbrance_curr")
    unsigned int	_encumbranceCurr;
#pragma db column("encumbrance_pct")
    unsigned int	_encumbrancePct;
#pragma db column("encumbrance_max")
    unsigned int	_encumbranceMax;
    int     _renown;
    int		_liability;
    int		_capital;
    int		_wanted;

    agency::deptnum _dept;
    
	// TODO Pull the list of titles dynamically from DB with Titles()
//#pragma db unordered
//    std::vector<std::string> _titles;

    boost::shared_ptr<Team>		_team;
    bool		_on_team;

#pragma db transient
	boost::shared_ptr<Dossier> _dossier;

};


//! @class Dossier
//! @brief A character's dossier
//! Top-level class that holds and is responsible for memory of all characters
//! that are online.
class Dossier
{
public:
	Dossier(entity_t a) { _agent = a; }

	entity_t 	Agent() { return _agent; }


private:
    entity_t	_agent;

};



#endif	/* _GOVT_CHARACTER_H */

